Expose ngnix ingress controller as Daemon-set

9/18/2019

I am trying to install and use the nginx-ingress to expose services running under kubernetes cluster and I am following this instructions.

In step 4 it's noted that :

If you created a daemonset, ports 80 and 443 of the Ingress controller container are mapped to the same ports of the node where the container is running. To access the Ingress controller, use those ports and an IP address of any node of the cluster where the Ingress controller is running.

That mean that the daemonset will be listening on ports 80 and 443 to forward the incoming traffic to the service mapped by an ingress.yaml config file.

But after running the instruction 3.2 kubectl apply -f daemon-set/nginx-ingress.yaml the daemon-set was created but nothing was listening on 80 or 443 in all the cluster's nodes.

Is there a problem with the install instruction or am I missing something there.

-- farhawa
docker
kubernetes
nginx
nginx-ingress

2 Answers

9/23/2019

As mentioned by Hang du (+1) According to the default setting in your cluster for --proxy-mode:

Which proxy mode to use: 'userspace' (older) or 'iptables' (faster) or 'ipvs'. If blank, use the best-available proxy (currently iptables). If the iptables proxy is selected, regardless of how, but the system's kernel or iptables versions are insufficient, this always falls back to the userspace proxy.

Assuming you have nginx-ingress-controller-xxx controller in kube-system namespace you can use this command to verify this parameters on your side:

sudo iptables-save | grep $(kubectl get pods -n kube-system -o wide | grep nginx-ingress-controller-xxx | awk '{print $6}')

More information about iptables/netfilter you can find here and here.

Additional resources:

Update:

HostNetwork - Controls whether the pod may use the node network namespace. Doing so gives the pod access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other pods on the same node.

So in addition to the above answer:

In order to bind ports 80 and 443 directly to Kubernetes nodes' network interfaces you can set-up hostNetwork: true (but it's not recommended):

Enabling this option exposes every system daemon to the NGINX Ingress controller on any network interface, including the host's loopback. Please evaluate the impact this may have on the security of your system carefully.

-- Hanx
Source: StackOverflow

9/19/2019

It is not the typical Listen which you can get from the output of netstat. It is "listened" by iptables. The following is the iptables rules for the ingress controller on my cluster node.

-A CNI-DN-0320b4db24e84e16999fd -s 10.233.88.110/32 -p tcp -m tcp --dport 80 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-0320b4db24e84e16999fd -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.233.88.110:80
-A CNI-DN-0320b4db24e84e16999fd -s 10.233.88.110/32 -p tcp -m tcp --dport 443 -j CNI-HOSTPORT-SETMARK
-A CNI-DN-0320b4db24e84e16999fd -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.233.88.110:443

10.233.88.110 is the ip address of the ingress controller running on that node.

$ kubectl get pod -n ingress-nginx -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
ingress-nginx-controller-5rh26   1/1     Running   1          77d   10.233.83.110   k8s-master3   <none>           <none>
ingress-nginx-controller-9nnwl   1/1     Running   1          77d   10.233.88.110   k8s-master2   <none>           <none>
ingress-nginx-controller-ckkb2   1/1     Running   1          77d   10.233.68.111   k8s-master1   <none>           <none>

Edit When a request comes to port 80/443, the iptables will apply DNAT rule to this request which modify the destination IP to the ip address of the ingress controller. The actual listen is inside the ingress controller container.

-- Hang Du
Source: StackOverflow