Installing MicroK8s on Mac OS X

According to the official website https://microk8s.io/, MicroK8s is a low-ops, minimal production Kubernetes for dev, cloud, cluster, workstations, Edge, and IoT. It is according to the documentation the smallest, fastest, fully-conformant Kubernetes that tracks upstream releases and makes clustering trivial.

It is maintained by Canonical the company behind Ubuntu.

Installing microk8s on Mac OS X is straight forward with Homebrew. However, there is not much resources available on troubleshooting and configuring microk8s on Mac OS X at the time of writing this entry.

This blog post serves two purposes. Beside providing you the reader with clear and clean How-To guide, this post will serve as my personal notes on the matter, in case, in the future, I am stuck while trying to configure microk8s.In the following I will try to lay out the commands needed to successfully install and configure microk8s.

Installing microk8s

brew install ubuntu/microk8s/microk8s
microk8s install --cpu 2 --mem 8 --disk 40

That should install microk8s. You could check the status of microk8s using:

microk8s status --wait-ready

Under the hood, Microk8s is provisioned on multipass; a VM orchestrator, which abstracts your operating system, which is especially useful on non-Linux based machines by Canonical  You can confirm that the VM has been provisioned with the requested via the multipass CLI:

multipass info -all

This command will print all info on all VM ochestrated by multipass on the device. By now, there should be at least one entry in the list with the name microk8s-vm which is the ubuntu VM where the Kubernetes cluster will run. You can ssh into the VM using another multipass CLI command:

multipass shell microk8s-vm

I find multipass shell particularly useful for quickly debugging issues, and to make sure everything is where it is supposed to be, especially when transferring files from Mac OS X to the VM.

So microk8s is now installed in a VM instance called microk8s-vm that is orchestrated by multipass on your Mac OS X machine with the CPU, Memory, and Disk space you’ve allocated when.

Microk8s comes with many add-ons such as the standard Kubernetes dashboard, the CoreDNS, the Ingress controller, the built-in registry and much more. Use the following command to enable the add-ons:

microk8s enable dns dashboard ingress registry 

If something went wrong deleting the microk8s and starting all over again is easy:

multipass delete microk8s-vm
multipass purge

To configure the installation, you might consider adding some configuration files to the microk8s-vm, but since the microk8s-vm instance is a VM, it is isolated from the OS of the host and thus moving data back and forth require some command line ninja. There are several ways to move files to the VM one of then is to mount a host folder on the VM OS and then us it as a shared folder between the host and the VM.

multipass mount ~/code cloud-host

you can unmount it with:

multipass unmount cloud-host

This works great if you are going to ssh into the VM and move or copy the files from the shared (mounted) folder to the destination folder on the VM file system. However if you want to programatically copy a specific file from the host filesystem the a specific folder on the VM with specific ownership and permissions then you can use the multipass transfer command. Let’s assume you want to move file foo.txt to the folder boo on the host:

multipass transfer foo.txt microk8s-vm:boo/foo.txt

Here the folder boo must already exist on microk8s-vm. also the destination foo.txt will be owned by the user ubuntu. If you want to move a file to a folder /boo/goo regardless if it exists or not, and then set the ownership of the file to a specific user/group on the VM machine you will have to do some more work:

  multipass exec microk8s-vm -- sudo mkdir -p /boo/goo
  multipass transfer foo.txt microk8s-vm:foo.txt
  multipass exec microk8s-vm -- sudo mv foo.txt /boo/goo
  multipass exec microk8s-vm -- sudo chown -R user:group /boo/goo/foo.txt

… and yes of course, I created a small bash script that does all that in one go. I used this great minimalistic bash script template provided in this great blog post. You can download the bash script cli template from here. You can find the script to install and configure microk8s on Mac OS X below.

#!/usr/bin/env bash

set -Eeuo pipefail

# Try to get the script dir
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)

# Try to clean up
trap cleanup SIGINT SIGTERM ERR EXIT

cleanup() {
  trap - SIGINT SIGTERM ERR EXIT
  # script cleanup here
  msg "${GREEN}Cleaning up...${NOFORMAT}"
}

# Usage
usage() {
  cat <<EOF
Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] arg1 [arg2...]

Installs microk8s on Mac OS X

...
EOF
  exit
}

# Nice colors
setup_colors() {
  if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then
    NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m'
  else
    NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''
  fi
}

# msg is meant to be used to print everything that is not a script output.
msg() {
  echo >&2 -e "${1-}"
}

# Fancy exit
die() {
  local msg="${1}"
  local code=${2-1} # default exit status 1
  msg "$msg"
  exit "$code"
}

parse_params() {
  # default values of variables set from params
  flag=0
  param=''

  while :; do
    case "${1-}" in
    -h | --help) usage ;;
    -v | --verbose) set -x ;;
    --no-color) NO_COLOR=1 ;;
    # -f | --flag) flag=1 ;; # example flag
    -f | --force) force=1 ;; # force reinstalls
    -c | --cpu) # cpu
      cpu="${2-}"
      shift
      ;;
    -m | --mem) # mem
      mem="${2-}"
      shift
      ;;
    -d | --disk) # disk
      disk="${2-}"
      shift
      ;;
    -?*) die "Unknown option: $1" ;;
    *) break ;;
    esac
    shift
  done

  args=("$@")

  # check required params and arguments
  # [[ -z "${param-}" ]] && die "Missing required parameter: param"
  # [[ ${#args[@]} -eq 0 ]] && die "Missing script arguments"

  return 0
}

install_microk8s_macosx(){

msg "${GREEN}Installing MicroK8s on MacOSX...${NOFORMAT}"
  # check whether ubuntu/microk8s/microk8s is installed...
  msg "${GREEN}Installing the homebrew formula ubuntu/microk8s/microk8s${NOFORMAT}"
  if brew ls --versions ubuntu/microk8s/microk8s >/dev/null; then
    # The package is installed
    msg "The homebrew formula ubuntu/microk8s/microk8s is already installed"
  else
    # The package is not installed
    brew install ubuntu/microk8s/microk8s
  fi
  # check the status of microk8s-vm
  msg "${GREEN}Preparing the microk8s-vm${NOFORMAT}"

  if ! microk8s --help >/dev/null; then
    msg "microk8s-vm does not exists"
    microk8s install --cpu "${cpu}" --mem "${mem}" --disk "${disk}"
    MULTIPASS_MICROK8S_VM_INFO=$(multipass info microk8s-vm)
  else
    msg "microk8s-vm already exists"
    if [[ force == 1 ]]; then
      # force reinstall
      multipass delete micro8s-vm
      multipass purge
      install_microk8s_macosx
      return
    fi
    MULTIPASS_MICROK8S_VM_INFO=$(multipass info microk8s-vm)
    MULTIPASS_MICROK8S_VM_STATE=$(echo "${MULTIPASS_MICROK8S_VM_INFO}" | grep State | awk -F' ' '{print $NF}')
    # there is a microk8s-vms
    if [[ MULTIPASS_MICROK8S_VM_STATE == 'Deleted' ]]; then
      multipass purge
      install_microk8s_macosx
      return
    fi
    if [[ MULTIPASS_MICROK8S_VM_STATE == 'Running' ]]; then
      msg "${GREEN}microk8s-vm is running${NOFORMAT}"
    fi
  fi
  msg "microk8s-vm information:${YELLOW}"
  echo "${MULTIPASS_MICROK8S_VM_INFO}"
  MULTIPASS_MICROK8S_VM_IP=$(echo "${MULTIPASS_MICROK8S_VM_INFO}" | grep IPv4 | awk -F' ' '{print $NF}')

  msg "${NOFORMAT}Status on the Kubernetes cluster on microk8s-vm:${YELLOW}"
  msg "${NOFORMAT}-"
  
  msg "${GREEN}Enabling microk8s Add-Ons:${NOFORMAT}"
  microk8s enable dashboard
  microk8s enable dns
  microk8s enable registry
  microk8s enable ingress
  msg "${GREEN}Restarting microk8s...${NOFORMAT}"
  microk8s stop >/dev/null
  microk8s start >/dev/null
  microk8s status --wait-ready
}

parse_params "$@"
setup_colors

# script logic here
msg "${GREEN}Read parameters:${NOFORMAT}"
msg "- flag: ${flag}"
msg "- param: ${param}"
msg "- arguments: ${args[*]-}"

install_microk8s_macosx

msg "${GREEN}Done${NOFORMAT}"