EDIT: I rewrote the question with a fully reproducible example.
I have a sample Django app with the base getting started https://docs.djangoproject.com/en/3.2/intro/tutorial01/, that is, there are two paths /admin and /polls.
If I deploy the app using NodePort, I can access both paths without issues. However, I haven't managed to do the same with Nginx ingress controller. I have tried several combinations of annotations and paths to no avail.
So, assume this yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: django
name: django
spec:
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- image: "ay0o/django-ingress:latest"
name: django
# ---
# apiVersion: v1
# kind: Service
# metadata:
# name: django
# spec:
# ports:
# - nodePort: 31000
# port: 8000
# targetPort: 8000
# selector:
# app: django
# type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: django
spec:
ports:
- port: 8000
selector:
app: django
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- http:
paths:
- path: /django
pathType: Prefix
backend:
service:
name: django
port:
number: 8000when I use NodePort, http://localhost:31000/admin and http://localhost:31000/polls work fine.
when I use Ingress, http://localhost/django returns a 404 from django (because the path is neither admin nor polls), but http://localhost/django/admin and http://localhost/django/polls return a 404 from nginx, meaning the ingress is not properly routing.
so, what should I change so that http://localhost/django/admin and http://localhost/django/polls will not return 404?
I think you shouldn't has both of them managing the routing path. You have to choose one of them. This is because Ingress was built to routing the traffic through cluster for microservices. If you want to really use it, you have to split your application on two separate services that accepts requests just at /. And let the routing with Ingress. Look at this page:
https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout
If you don't want to change your application or if it's just for testing purposes. The way it's deploy a Ingress with two rules:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
namespace: default
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /admin
pathType: Prefix
backend:
service:
name: django
port:
number: 80
- path: /polls
pathType: Prefix
backend:
service:
name: django
port:
number: 80This will accept the requests on both of the path's.
I have come to the conclusion that it's not possible to use path-based Ingress for a Django app, probably due to something related to Django's internals.
Every example out there uses host-based rules, and indeed, that just work. For example, the Ingress above can be changed to the following, and it will work.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- host: localhost
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: django
port:
number: 8000If anyone come up with a solution using path-based routing, feel free to answer the question.