How nginx handles overlapping ingress configurations - Sat, Mar 23, 2024
How nginx handles overlapping ingress configurations
How nginx handles conflicting ingress configurations
In my current project we have a nginx ingress controller as a managed service for handling ingress traffic. Configuring ingresses is done through various annotations on the ingress manifests like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/whitelist-source-range: 10.108.122.141/32
With the annotations above the uri of the target is rewritten and only clients with a specific IP
may
access the backend service.
What happens in the background when you apply an ingress manifest to your kubernetes cluster is that the ingress
controller picks up the manifest, parses it and creates a matching nginx configuration. Which in turn is
read by the Pods of the nginx controller and applied.
The question
While this is perfectly clear, it was unclear at that point in time how the controller deals with overlapping
ingress rule configurations. For example if two ingress manifests contain the same host
name or identical paths
.
So I created a small helm chart
to deploy different ingress manifests and do some tests.
The test setup
The above-mentioned helm charts contains a StatefulSet with two replicas. The image deployed is a simple http echo server . In addition, the helm chars deploys two ingresses. Each having on of the replicas as its backend service. That way I can easily see two which Pod the request was forwarded for. The ingress can be configured solely by values:
ingress:
hosts:
- host: ingress-test-1.example.com
paths:
- path: /ingress-test
serviceName: ingress-test-0
- host: ingress-test-2.example.com
paths:
- path: /ingress-test-2
serviceName: ingress-test-1
The values above for example will result in on ingress being created with a rule for host ingress-test-1.example.com
and path /ingress-test
connecting to the first Pod as a backend and a rule with ingress-test-2.example.com
and /ingress-test-2
forwarding traffic to the second Pod.
This setup lets me change the ingress configuration very easily.
Testing conflicting configurations
Same configuration
The first configuration contained the exact same rules for host
(ingress-test-1.example.com
) and path
(/ingress-test
).
After deployment, I tested which Pod received the traffic with a simple curl:
curl --header "Host: ingress-test-1.example.com" http://80:10.118.146.125/ingress-test
Where 10.118.146.125
is the IP of the ingress controller. The result was that all traffic was always directed towards
the first Pod.
Different hosts same path
The second configuration contained different hosts but the same path. The curls to test this configuration looked like this:
curl --header "Host: ingress-test-1.example.com" http://10.108.166.195/ingress-test
curl --header "Host: ingress-test-2.example.com" http://10.108.166.195/ingress-test
As one would expect the traffic was routed to the correct Pods since the host is the differentiator to unambiguously determine the destination.
Same host different path
No surprises here since this time the path is the distinguishing feature. This is also true for sub-paths. For example if you have a configuration like this:
hosts:
- host: ingress-test-1.example.com
paths:
- path: /ingress-test
serviceName: ingress-test-0
- host: ingress-test-1.example.com
paths:
- path: /ingress-test/sub-path
serviceName: ingress-test-1
Curls for /ingress-test/sub.path
will got to the backend ingress-test-1
because it is more explicit.
Conclusion
Overlapping ingress configurations do not really produce surprising results. As one would expect, the controller tries to find the most specific rule. The only exception being configurations with exact same rules. In this case the expression First come, first served holds true.