Access Minikube service from OSX Host
Background
Deploying applications to Kubernetes has been getting better and better. Things like Deployments, Dynamic Volume Provisioning and other features are allowing folks to focus on the apps more-so than the infrastructure which is great.
However, in a development model, you want more access to the cluster to allow for easier debugging and access.
I use Minikube all the time in my day-to-day job to test out new Operators I’m working on or to deploy an application locally to test out some features.
The one component that was always difficult was how to connect to services on Minikube. The only real way today has been to expose the service via a NodePort which works, but it’s difficult if since now there’s a different configuration to deal with. The service type now has to be NodePort when I only want it to be ClusterIP (meaning no outside cluster access). Additionally, that port is dynamic, so now I’ve got to find out the new port each time or set it statically.
Solution
In slack the other day, I saw a post from Dale Hamel (@dalehamel-shopify on Slack), which outlined a way to route traffic from your host machine to the minikube cluster allowing you to curl Kubernetes services via ClusterIP or DNS name.
There are just a few simple commands that you need to do to set this up, and a big thanks to Dale for sharing with everyone!
Implementation
NOTE: These instructions are build for an OSX system, but can be translated to Linux as well pretty easily.
Create a route to allow traffic from the host machine to route to the minikube IP:
# Remove any existing routes
$ sudo route -n delete 10/24 > /dev/null 2>&1
# Create route
$ sudo route -n add 10.0.0.0/24 $(minikube ip)
Create a DNS resolver to allow traffic to use the minikube internal DNS server for resolution:
$ sudo cat <<EOF >/etc/resolver/svc.cluster.local
nameserver 10.0.0.10
domain svc.cluster.local
search svc.cluster.local default.svc.cluster.local
options ndots:5
EOF
Update mac dns resolver, then REBOOT:
sudo defaults write /Library/Preferences/com.apple.mDNSResponder.plist AlwaysAppendSearchDomains -bool YES
Get the list of interfaces:
# xhyve uses "bridge100" / virtualbox uses "bridge0"
$ ifconfig 'bridge100' | grep member | awk '{print $2}'
Open up the firewall to allow access:
# Take all interfaces from the previous command and apply
$ sudo ifconfig bridge100 -hostfilter en5
Test it out!
# --- Delete current route:
$ sudo route -n delete 10/24 > /dev/null 2>&1
Password:
# --- Add new route:
$ sudo route -n add 10.0.0.0/24 $(minikube ip)
add net 10.0.0.0: gateway 192.168.64.30
# --- Get interfaces:
$ ifconfig 'bridge100' | grep member | awk '{print $2}'
en5
# --- Set firewall:
$ sudo ifconfig bridge100 -hostfilter en5
# --- Get services:
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch 10.0.0.181 <none> 9200/TCP 2m
elasticsearch-discovery 10.0.0.88 <none> 9300/TCP 2m
es-data-svc 10.0.0.55 <none> 9300/TCP 2m
kubernetes 10.0.0.1 <none> 443/TCP 8m
# --- Curl service by IP:
$ curl -k https://10.0.0.181:9200
{
"name" : "71b5524c-524c-4f4c-9621-e45c5c34f22c",
"cluster_name" : "myesdb",
"cluster_uuid" : "Y0D14nKKRTuPH8x2Yq3kuQ",
"version" : {
"number" : "5.3.1",
"build_hash" : "5f9cf58",
"build_date" : "2017-04-17T15:52:53.846Z",
"build_snapshot" : false,
"lucene_version" : "6.4.2"
},
"tagline" : "You Know, for Search"
}
# --- Curl service by DNS:
$ curl -k https://elasticsearch:9200
{
"name" : "71b5524c-524c-4f4c-9621-e45c5c34f22c",
"cluster_name" : "myesdb",
"cluster_uuid" : "Y0D14nKKRTuPH8x2Yq3kuQ",
"version" : {
"number" : "5.3.1",
"build_hash" : "5f9cf58",
"build_date" : "2017-04-17T15:52:53.846Z",
"build_snapshot" : false,
"lucene_version" : "6.4.2"
},
"tagline" : "You Know, for Search"
}