27

I'm trying to get an ingress controller working in Minikube and am following the steps in the K8s documentation here, but am seeing a different result in that the IP address for the ingress controller is different than that for Minikube (the example seems to indicate they should be the same):

$ kubectl get ingress
NAME              HOSTS              ADDRESS     PORTS   AGE
example-ingress   hello-world.info   10.0.2.15   80      12m

$ minikube ip
192.168.99.101

When I try to connect to the Minikube IP address (using the address directly vs. adding it to my local hosts file), I'm getting a "Not found" response from NGINX:

$ curl http://`minikube ip`/
<html>
    <head><title>404 Not Found</title></head>
    <body>
        <center><h1>404 Not Found</h1></center>
        <hr><center>openresty/1.15.8.1</center>
    </body>
</html>

When I try to connect to the IP address associated with the ingress controller, it just hangs.

Should I expect the addresses to be the same as the K8s doc indicates?

Some additional information:

$ kubectl get nodes -o wide
NAME       STATUS   ROLES    AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE              KERNEL-VERSION   CONTAINER-RUNTIME
minikube   Ready    master   2d23h   v1.16.0   10.0.2.15     <none>        Buildroot 2018.05.3   4.15.0           docker://18.9.9

$ kubectl get ingresses example-ingress -o yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","metadata":{"annotations":{"nginx.ingress.kubernetes.io/rewrite-target":"/$1"},"name":"example-ingress","namespace":"default"},"spec":{"rules":[{"host":"hello-world.info","http":{"paths":[{"backend":{"serviceName":"web","servicePort":8080},"path":"/"}]}}]}}
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  creationTimestamp: "2019-10-28T15:36:57Z"
  generation: 1
  name: example-ingress
  namespace: default
  resourceVersion: "25609"
  selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/example-ingress
  uid: 5e96c378-fbb1-4e8f-9738-3693cbce7d9b
spec:
  rules:
  - host: hello-world.info
    http:
      paths:
      - backend:
          serviceName: web
          servicePort: 8080
        path: /
status:
  loadBalancer:
    ingress:
    - ip: 10.0.2.15
ShawnC
  • 559
  • 1
  • 6
  • 18
  • Have you added the NodePort along with `minikube ip`? something like, `http://minikubeIP:port/` – Kamol Hasan Oct 25 '19 at 15:58
  • @KamolHasan, doing this worked: `$ kubectl get service web NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web NodePort 10.107.6.230 8080:31349/TCP 77m $ minikube ip 192.168.99.101 $ curl http://192.168.99.101:31349 Hello, world! Version: 1.0.0 Hostname: web-9bbd7b488-bd2wm` But I have to admit that I don't understand. If my ingress controller is configured for a different IP:port why doesn't that work? – ShawnC Oct 25 '19 at 16:13
  • Please, send me the output of these commands: `$ kubectl get nodes -o wide` `$ kubectl get ingresses example-ingress -o yaml` You are running this minikube on top of a Bare Metal machine? Linux, Windows, Mac Os? If you are running in the cloud, in which provider? – PjoterS Oct 28 '19 at 12:13
  • @PjoterS, I'm running this on macOS 10.14.6 with minikube v1.5.0. The output from the first command you recommended: `minikube Ready master 2d22h v1.16.0 10.0.2.15 Buildroot 2018.05.3 4.15.0 docker://18.9.9` Not sure how best to provide the output from the second in a comment post here. Suggestions? – ShawnC Oct 28 '19 at 15:47
  • @ShawnC as OP you can always edit your question with proper formatting. – PjoterS Oct 28 '19 at 15:50
  • @PjoterS, updated the OP as suggested. To clarify, when following the example steps in the K8s docs, when creating the [ingress resource] (https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/#create-an-ingress-resource), the doc seems to indicate the IP address of the ingress resource should be the same as Minikube, but that's not what I'm seeing (and why I assume I'm missing some fundamental point). – ShawnC Oct 28 '19 at 17:35

7 Answers7

38

Here’s what worked for me:

  1. minikube start

  2. minikube addons enable ingress

  3. minikube addons enable ingress-dns

  4. Wait until you see the ingress-nginx-controller-XXXX is up and running using Kubectl get pods -n ingress-nginx

  5. Create an ingress using the K8s example yaml file

  6. Update the service section to point to the NodePort Service that you already created

  7. Append 127.0.0.1 hello-world.info to your /etc/hosts file on MacOS (NOTE: Do NOT use the Minikube IP)

  8. Run minikube tunnel ( Keep the window open. After you entered the password there will be no more messages, and the cursor just blinks)

  9. Hit the hello-world.info ( or whatever host you configured in the yaml file) in a browser and it should work

Mahmoud
  • 698
  • 1
  • 8
  • 9
15

I've reproduced your scenario in a Linux environment (on GCP) and I also have different IPs:

user@bf:~$ minikube ip
192.168.39.144

user@bf:~$ kubectl get ingresses
NAME              HOSTS   ADDRESS           PORTS   AGE
example-ingress   *       192.168.122.173   80      30m

Your problem is not related to the fact you have different IPs. The guide instructs us to create an ingress with the following rule:

spec:
  rules:
  - host: hello-world.info

This rule is telling the ingress service that a DNS record with hello-world.info name is expected. If you follow the guide a bit further, it instructs you to create an entry on your hosts file pointing to your ingress IP or Minikube IP.

Note: If you are running Minikube locally, use minikube ip to get the external IP. The IP address displayed within the ingress list will be the internal IP.
Source: Set up Ingress on Minikube with the NGINX Ingress Controller

(if you want to curl the IP instead of DNS name, you need to remove the host rule from your ingress)

It should look like this:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
     paths:
     - path: /
       backend:
         serviceName: web
         servicePort: 8080

Apply your changes:

user@bf:~$ kubectl apply -f example-ingress.yaml

And curl the IP using -Lk options to surpass problems related to secure connections.

user@bf:~$ curl -Lk 192.168.39.144
Hello, world!
Version: 1.0.0
Hostname: web-9bbd7b488-l5gc9
Kamafeather
  • 8,663
  • 14
  • 69
  • 99
Mark Watney
  • 5,268
  • 2
  • 11
  • 33
  • 1
    I'm not sure how this came about, but now I'm getting the same IP address from `minikube ip` and `kubectl get ingress`. So updating /etc/hosts with this now correctly reaches the pod with `curl hello-world.info`. No idea why, but I'm going to try with the "real" deployment I'm building (the whole reason for wanting to test it first with Minikube) and see if that works. – ShawnC Oct 29 '19 at 13:00
  • It's great to hear that. If you have any problem during your "real" implementation, don't hesitate on posting a question. – Mark Watney Oct 31 '19 at 08:53
  • 1
    If this was allowed by Ingress it would be so much more useful. Not being able to leave the host field out really limits testing. – user959690 Nov 17 '20 at 23:16
  • I kept using the loop back address in the hosts file for mapping domain name. Your answer saved me! – Akash Agarwal Dec 09 '20 at 03:15
5

In addition to the accepted answer, minikube now has a tunnel command which allows you generate external ip addresses for your services which can be accessed directly on your host machine without using the general minikube ip.

Run minikube tunnel in a separate terminal. This runs in the foreground as a daemon. In a different terminal, execute your kubectl apply -f <file_name> command to deploy your desired service. It should generate an ip address for you that is routed directly to your service and available on port 80 on that address.

More here on the minikube documentation: https://minikube.sigs.k8s.io/docs/tasks/loadbalancer/

Samuel_NET
  • 345
  • 3
  • 9
3

I got Minikube on Windows 11 to work for me

minikube start --vm-driver=hyperv

Install minikube Ingress Controller

minikube addons enable ingress
minikube addons enable ingress-dns

Deploy Helm Chart

helm install ...

Get Kubernetes IP Address

nslookup <host-found-in-ingress> $(minikube ip)

Add to etc/host

<minikube-ip> <domain-url>

Live!

curl <domain-url>
Victor
  • 59
  • 6
  • This is the proper way. Here is also the doc from minikube https://minikube.sigs.k8s.io/docs/drivers/hyperv/ – Alex Escu Mar 22 '23 at 13:44
2

Your problem comes from how you start minkube. If you use just "minikube start" it will use your local docker desktop. This works fine for most scenario but for ingress, for some reason will not allow you to expose the external ip of ingress.

The proper way to achieve this is to start minikube with hyberv driver. There are 2 steps:

  • Start windows powershell in Admin mode *important, and run commnad:

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

  • If not already active you need to restart. You can also configure it manually from Windows Features.

  • Start minikube with driver hyperv. Also requires to use Powershell in Admin. If you don't have admin rights, you probably can not do this

    minikube start --driver=hyperv

  • Set the kyperv as default:

    minikube config set driver hyperv

  • This last step requires a restart of cluster with delete, and the step is optional.

Complete documentation on how to setup minikube with hyperv: https://minikube.sigs.k8s.io/docs/drivers/hyperv/

Sample how to setup ingress: https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/

Alex Escu
  • 147
  • 1
  • 6
0

For Docker Desktop Driver (Default)

You should create a tunnel to your cluster with :

minikube tunnel

Amine Bk
  • 41
  • 2
0

You must determine which "docker mode" you are running. It can be "docker desktop" or "docker engine":

  • Check docker mode:

    docker version | grep "Docker Engine"

    Client: Docker Engine - Community

    docker version | grep "Docker Engine"

    Client: Docker Engine - Community

    Server: Docker Engine - Community

If you don't see the server, you are using Docker Desktop to run docker The best solution would be to turn it off.

When you run minikube start you will get a warning if you are using Docker Desktop

❗ For an improved experience it's recommended to use Docker Engine instead of Docker Desktop. Docker Engine installation instructions: https://docs.docker.com/engine/install/#server

  1. Enable ingress in minicube and load all preparatory data. I will use https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/ as a base:

     minikube addons enable ingress
     kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0
     kubectl expose deployment web --type=NodePort --port=8080
     kubectl apply -f https://k8s.io/examples/service/networking/example-ingress.yaml
     kubectl get ingress
    
  2. Test inside and outside the minikube cluster 3.1 Internal:

     minikube ssh
     curl -H "Host: hello-world.info" 127.0.0.1 #its work
    

    3.2 External Docker Engine

     curl -H "Host: hello-world.info" $(minikube ip) # only for docker engine
    

    3.3 External Docker Desktop

     ping $(minikube ip) # you won't see a response if it's docker desktop
     ssh -i $(minikube ssh-key) -p "$(docker port minikube 22/tcp | awk -F ':' '{print $2}')" docker@$(docker port minikube 22/tcp | awk -F ':' '{print $1}') #its work
    

    make ssh tunnel

     ssh -i $(minikube ssh-key) -p "$(docker port minikube 22/tcp | awk -F ':' '{print $2}')" docker@$(docker port minikube 22/tcp | awk -F ':' '{print $1}') -L 8008:localhost:80
     curl -H "Host: hello-world.info" 127.0.0.1:8008 #its work
    
Anton
  • 36
  • 4