Proxying services into minikube

Connecting to your services running within minikube from your laptop is quite easy. You can setup a NodePort service or Ingress resource and access it with theminikube ip command. Or you can always setup port forwarding using kubectl. What if you want to access services running natively on your laptop from the minikube VM or from the pods running in the VM?

Why would you want to do this?

By default, minikube launches with 2 GB of RAM and 2 cores and uses VirtualBox as the VM driver. You can always increase the RAM and CPU but, for tools like Elasticsearch, its not quite enough. So the solution that I wanted to do was to export services running on my macbook pro like Elasticsearch into minikube. But minikube uses host only network and hence neither the VM or the pods running inside the VM can use the IP address provided by the router for your dev machine. However, from the dev machine, we can access the VMs created on this network. So we’ll tunnel our way into the minikube VM using SSH. Here is how to do it.

Once you launch minikube, you can ssh into the machine using the following command.

> minikube ssh
_ _
_ _ ( ) ( )
___ ___ (_) ___ (_)| |/') _ _ | |_ __
/' _ ` _ `\| |/' _ `\| || , < ( ) ( )| '_`\ /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )( ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)
$ _

Once you are in, you can edit the /etc/ssh/sshd_config file and set the GatewayPorts directive to yes. Its set to no by default. Once you have edited the file, you will have to restart the SSH daemon.

$ sudo systemctl reload sshd

Once done, you can expose any locally running service inside the VM. Minikube uses the VirtualBox driver by default and creates a host-only network starting with the IP 10.0.2.15. You can usually bind a local service to the remote URL using the following command.

ssh user@host -R remotebindaddr:remoteport:localaddr:localport

For example, if I have to expose my Elasticsearch service running locally on my laptop to the minikube VM, I will have to do the following.

ssh -i $(minikube ssh-key) docker@$(minikube ip) -R 9292:localhost:9200

This exposes the elasticsearch service running on my machine on port 9200 to be bound on all addresses at port 9292 on the VM. Now running the following confirms that it is listening on 9292.

# within the minikube VM (via <minikube ssh>)
$ netstat -an | grep 9292
tcp 0 0 0.0.0.0:9292 0.0.0.0:* LISTEN
tcp 0 0 :::9292 :::* LISTEN

Now that this works, we can curl 9292 locally to verify that it is indeed giving us the cluster details.

# within the minikube VM
$ a=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
$ curl http://${a}:9292/
{
"name" : "Kb-ZnGh",
"cluster_name" : "elasticsearch_vagmi",
"cluster_uuid" : "suKQ-vxYRK6bLZdWcxPHpA",
"version" : {
"number" : "6.2.4",
"build_hash" : "ccec39f",
"build_date" : "2018-04-12T20:37:28.497551Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}

Voila! We are now able to access the Elasticsearch service from minikube VM. If you need to access Elasticsearch from a pod, you will have to use the host only IP of the VM (10.0.2.15).