How to use minikube + qemu2 + ingress-dns on macOS
This is a guide on how to use minikube
and qemu2
on macOS to run Kubernetes locally on your machine. The guide covers the installation of required packages using brew
and provides step-by-step instructions to help you get started. If you are interested in running Kubernetes on your macOS and prefer to use open-source solutions, this guide is for you.
My personal requirements:
- Install packages using
brew
: https://brew.sh/ - I don't want to use Docker or Podman
- I use open-source solutions, if possible
My setup:
- Laptop model: MacBook Pro 2019, Intel Core i9
- OS: macOS Sonoma, version 14.3.1
Notes:
- I don't know if this works on MacBooks with a M chip.
So, what are those components?
QEMU
: An open-source virtualization software that enables emulation of various architectures and devices, allowing users to run virtual machines on their systems.socket_vmnet
: socket_vmnet provides vmnet.framework support for QEMU. Learn more about it at https://github.com/lima-vm/socket_vmnet and https://developer.apple.com/documentation/vmnetminikube
: A tool that allows you to run Kubernetes on your local machine, making it easy to develop and test your applications locally.dnsmasq
: DNS service for ingress controllers running on your minikube server.
Install qemu as our driver
To install qemu, follow the guide available at:
https://www.qemu.org/download/#macos
It will probably ask you to use brew, with the following command:
Now, you will need to install the socket_vmnet
network support. Follow the installation instructions available at:
https://minikube.sigs.k8s.io/docs/drivers/qemu/#networking
If nothing has changed since I wrote this post, run the following commands:
Create your minikube cluster
With all the packages installed, let's start the minikube cluster. The following command will use qemu
, use the socket_vmnet
project for networking and install the default nginx
ingress after that:
When it finishes, you should be able to access the endpoint and get a 404
return code:
And that's it. Now, you should have everything you need to start developing on your macOS!
But man, you should just use Linux instead... kind
works with a single command and doesn't need all this mess...
How to have local domain for development?
Let's assume you want to test your application using custom domains, like my-app.exodus.test
. For that, you will need to have a wildcard that forwards the traffic to your minikube cluster. We will use the ingress-dns
add-on for that. We previously installed it, when we start the minikube cluster. In other to make our computer to read information from it, we must create a proper resolver.
Now, let's create the resolver to use it:
# Create the resolver directory
sudo mkdir -v /etc/resolver
# Add your nameserver to resolvers
sudo bash -c 'echo "nameserver "$(minikube ip) > /etc/resolver/test'
sudo bash -c 'echo "domain test" >> /etc/resolver/test'
sudo bash -c 'echo "search_order 1" >> /etc/resolver/test'
sudo bash -c 'echo "timeout 5" >> /etc/resolver/test'
# Reload the mDNS
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
# If you want to check the configuration, run
scutil --dns
Now, let's test it:
# Just to make sure, let's clean your DNS local cache
dscacheutil -q host -a name cafe.test
# Now, let's curl cafe.test
curl cafe.test
#> <html>
#> <head><title>404 Not Found</title></head>
#> <body>
#> <center><h1>404 Not Found</h1></center>
#> <hr><center>nginx</center>
#> </body>
#> </html>
If everything worked, now you are ready to create your first application! 😄
Create my first deployment + ingress
Finally, if you want to create a simple default app
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- name: http
port: 80
selector:
app: web
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: docker.io/nginx
name: nginx
ports:
- containerPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: cafe.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
EOF
Now, you should be able to go your browser and open the http://cafe.test page!
Troubleshooting
I faced multiple issues I couldn't reliably reproduce. Examples:
- ISSUE: after restarting the machine, can't start the service
Error: Failure while executing; /bin/launchctl bootstrap system /Library/LaunchDaemons/homebrew.mxcl.socket_vmnet.plist
exited with 5.
$ HOMEBREW=$(which brew) && sudo ${HOMEBREW} services start socket_vmnet
#> Bootstrap failed: 5: Input/output error
#> Error: Failure while executing; `/bin/launchctl bootstrap system /Library/LaunchDaemons/homebrew.mxcl.socket_vmnet.plist` exited with 5.
# Solution
# simply restart the service
$ HOMEBREW=$(which brew) && sudo ${HOMEBREW} services restart socket_vmnet
# then start minikube again
minikube start --addons=ingress --driver=qemu --network=socket_vmnet