how to access external service using the minikube host's public ip address

11/17/2020

I've set up a minikube cluster on an Azure's Ubuntu instance that exposes an external service on the IP: 192.168.49.2:30000

curl 192.168.49.2:30000 returns the desired output. How can I access this service using a browser on my local machine using the azure host public IP address ?

-- user80
cloud
kubernetes
minikube

1 Answer

11/18/2020

Explanation:


EDIT:

OK, I see that docker driver by default uses 192.168.49.2 IP address:

azureuser@minikube:~$ minikube service web --url
http://192.168.49.2:31527

so most probably you've used this one. Although the further explanation is based on virtualbox example it can be fully applied also in this case, with the only difference that minikube runs as an isolated docker container and not as a VM. But if you run docker ps on your Azure VM instance you'll see only one container, named minikube:

azureuser@minikube:~$ docker ps
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS              PORTS                                                                                                      NAMES
af68ab219c6c        gcr.io/k8s-minikube/kicbase:v0.0.14   "/usr/local/bin/entr…"   53 minutes ago      Up 53 minutes       127.0.0.1:32771->22/tcp, 127.0.0.1:32770->2376/tcp, 127.0.0.1:32769->5000/tcp, 127.0.0.1:32768->8443/tcp   minikube

Only after running:

azureuser@minikube:~$ minikube ssh

and then:

docker@minikube:~$ docker ps

you'll see both the container running by your app Pod as well as kubernetes control plane components. The list is quite long so I won't put it here.

But it shows that your kubernetes cluster is in practice isolated in a very similar way from your Azure VM host as in case when it runs in a nested VM. The key point here is that minikube cluster's network is isolated from host VM network and NodePort Service is accessible only on the external IP of a VM or minikube docker container, not exposing any port on any of host VM network interfaces.


I've reproduced your case, assuming that you started your minikube with virtualbox driver, so please correct me if my assumption was wrong. You could've started it this way:

minikube start --driver=virtualbox

or simply:

minikube start

If you've installed VirtualBox on your minikube vm, it will be also automatically detected and virtualbox driver will be used.

OK, so let's pause for a moment at this point and take a closer look what such approach implies.

Your minikube runs inside your Azure VM but it doesn't run directly on it. Nested virtualization is used and your minikube kubernetes cluster actually runs on a vm inside another vm.

So if you've exposed your Deployment using NodePort service, it makes it available on the external IP address of minikube vm (which is nested vm). But this IP is external only from the perspective of this vm.

Let's ssh into our Azure VM and run:

azureuser@minikube:~$ minikube service web --url
http://192.168.99.100:31955

Your service name and address will be different but I'm showing it just to illustrate the idea.

Then run:

azureuser@minikube:~$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
3: vboxnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.99.1/24 brd 192.168.99.255 scope global vboxnet0
       valid_lft forever preferred_lft forever

As you can see 192.168.99.100 is reachable via vboxnet0 network interface as it's part of 192.168.99.0/24 network, used by virtualbox vm.

Therefore there are no means for it to be reachable without using additional port forwarding, not only on the external IP of the Azure VM but on any of its internal network interfaces. NodePort service exposes the Deployment only on the external IP of the nested VirtualBox VM (or other hypervisor), which is reachable from Azure VM host but it's not exposed on any of it's network interfaces so it cannot be reached from outside either.

Solution:

Did I just say port forwarding ? Fortunately kubectl makes it fairly easy task. If you haven't installed it so far on your Azure VM, please do it as minikube kubectl may not work. You can use for it the following command:

kubectl port-forward --address 0.0.0.0 service/<service-name> 8080:8080

which will forward the traffic destined to any of Azure VM addresses (also the public one) to your Service, which in this case doesn't even have to be of NodePort type, ClusterIP will also work.

Caveat: To be able to bind to a well known port such as 80 you need to run this command as root. If you use registered ports, starting from 1024 such as 8080 you don't need root access. So after running:

root@minikube:~# kubectl port-forward --address 0.0.0.0 service/web 80:8080

You should be able to access your app without any problems by using the external IP address of your Azure VM.

-- mario
Source: StackOverflow