Search code examples
kuberneteskubernetes-ingressnginx-ingress

Why do I have to edit /etc/hosts just sometimes when using nginx-ingress controller and resources in my local k8s environment?


Not sure if this is OS specific, but on my M1 Mac, I'm installing the Nginx controller and resource example located in the official Quick Start guide for the controller. for Docker Desktop for Mac. The instructions are as follows:

// Create the Ingress
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

// Pre-flight checks
kubectl get pods --namespace=ingress-nginx

kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=120s

// and finally, deploy and test the resource.
kubectl create deployment demo --image=httpd --port=80
kubectl expose deployment demo

kubectl create ingress demo-localhost --class=nginx \
  --rule=demo.localdev.me/*=demo:80

kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8080:80

I noticed that the instructions did not mention having to edit the /etc/hosts file, which I found strange. And, when I tested it by putting demo.localdev.me:8080 into the browser, it did work as expected!

But why? What happened that an application inside of a docker container was able to influence behavior on my host machine and intercept its web traffic without me having to edit the /etc/hosts file?

For my next test, I re-executed everything above with the only change being that I switched demo to demo2. That did not work. I did have to go into /etc/hosts and add demo2.localdev.me 127.0.0.1 as an entry. After that both demo and demo2 work as expected.

Why is this happening? Not having to edit the /etc/hosts file is appealing. Is there a way to configure it so that they all work? How would I turn it "off" from happening automatically if I needed to route traffic back out to the internet rather than my local machine?


Solution

  • I replicated your issue and got a similar behaviour on the Ubuntu 20.04.3 OS.

    The problem is that NGINX Ingress controller Local testing guide did not mention that demo.localdev.me address points to 127.0.0.1 - that's why it works without editing /etc/hosts or /etc/resolve.conf file. Probably it's something like *.localtest.me addresses:

    Here’s how it works. The entire domain name localtest.me—and all wildcard entries—point to 127.0.0.1. So without any changes to your host file you can immediate start testing with a local URL.

    Also good and detailed explanation in this topic.

    So Docker Desktop / Kubernetes change nothing on your host.

    The address demo2.localdev.me also points to 127.0.0.1, so it should work as well for you - and as I tested in my environment the behaviour was exactly the same as for the demo.localdev.me.

    You may run nslookup command and check which IP address is pointed to the specific domain name, for example:

    user@shell:~$ nslookup demo2.localdev.me
    Server:         127.0.0.53
    Address:        127.0.0.53#53
    
    Non-authoritative answer:
    Name:   demo2.localdev.me
    Address: 127.0.0.1
    

    You may try to do some tests with other hosts name, like some existing ones or no-existing then of course it won't work because the address won't be resolved to the 127.0.0.1 thus it won't be forwarded to the Ingress NGINX controller. In these cases, you can edit /etc/hosts (as you did) or use curl flag -H, for example:

    I created the ingress using following command:

    kubectl create ingress demo-localhost --class=nginx --rule=facebook.com/*=demo:80
    

    Then I started port-forwarding and I run:

    user@shell:~$ curl -H "Host: facebook.com" localhost:8080
    <html><body><h1>It works!</h1></body></html>
    

    You wrote:

    For my next test, I re-executed everything above with the only change being that I switched demo to demo2. That did not work. I did have to go into /etc/hosts and add demo2.localdev.me 127.0.0.1 as an entry. After that both demo and demo2 work as expected.

    Well, that sounds strange, could you run nslookup demo2.localdev.me without adding an entry in the /etc/hosts and then check? Are you sure you performed the correct query before, did you not change something on the Kubernetes configuration side? As I tested (and presented above), it should work exactly the same as for demo.localdev.me.