skip to Main Content

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: 8000

when 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?

2

Answers


  1. 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: 8000
    

    If anyone come up with a solution using path-based routing, feel free to answer the question.

    Login or Signup to reply.
  2. 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: 80
    

    This will accept the requests on both of the path’s.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search