Hosting django on aks behind nginx-ingress

11/6/2019

I am trying to host a django website on Azure kubernetes service behide nginx-ingress, and I would like my django web show under a path.

e.g. when access the default admin site, I would like to access it at http://example.com/django/admin instead of http://example.com/admin

I tried the configure below, when I access http://example.com/django/admin it will forward me to http://example.com/admin and show me 404 error from default ingress backend, as I set django debug to ture I assume this mean ingress did not send my request to my django service

# path example
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: django-ingress
  labels:
    app: django
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: django-service
          servicePort: 80
        path: /django(/|$)(.*)

so I try to curl -I -k http://example.com/django/admin, and it show something like below

HTTP/1.1 301 Moved Permanently
Server: openresty/1.15.8.2
Date: Wed, 06 Nov 2019 04:14:14 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /admin/

The same thing happen to any valid page in the site, if I curl -I -k http://example.com/django/any_valid_page it show below:

HTTP/1.1 301 Moved Permanently
Server: openresty/1.15.8.2
Date: Wed, 06 Nov 2019 04:14:14 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /any_valid_page/

I wonder it is caused by I am doing the test with the default django development web server? (i.e. python manage.py runserver)

If I try to host it at root like below, everything is fine...

# root example
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: django-ingress
  labels:
    app: django
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: django-service
          servicePort: 80
        path: /
-- Bill
azure
azure-aks
django
kubernetes
nginx-ingress

2 Answers

11/6/2019

Trying adding this

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: django-ingress
  labels:
    app: django
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    ingress.kubernetes.io/rewrite-target: /django
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: django-service
          servicePort: 80
        path: /django
-- Harsh Manvar
Source: StackOverflow

11/6/2019

Starting in Version 0.22.0, ingress definitions using the annotation nginx.ingress.kubernetes.io/rewrite-target are not backwards compatible with previous versions. In Version 0.22.0 and beyond, any substrings within the request URI that need to be passed to the rewritten path must explicitly be defined in a capture group. So make sure you have right version.

When using SSL offloading outside of cluster it may be useful to enforce a redirect to HTTPS even when there is no TLS certificate available. This can be achieved by using the nginx.ingress.kubernetes.io/force-ssl-redirect: "true" annotation in the particular resource.

I think your Ingress configuration file should look like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: django-ingress
  labels:
    app: django
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /django(/|$)(.*)
            backend:
              serviceName: django-service
              servicePort: 80

If you get 404 error, there is possible solution:

Please change https to http in the curl command?:

curl --resolve your-host:80:xx.xxx.xx.xxx http://my-host:80

To get the IP from kubectl get ing command, it is necessary to enable the reporting Ingress status feature. Take a look on: reporting-ingress-status.

There is the default server in the Ingress controller. It returns the Not Found page with the 404 status code for all requests for domains for which there are no Ingress rules defined. Those requests are not shown in the access log.

Since you're getting a 404, this means that the host header of your requests doesn't match with the host field in the Ingress resource. To set the host header in curl, please see previous curl commands. Optionally, you can also do:

curl http://<ip> -H "host: example.com"

Please take a look on ngnix-ingress, server-side-https-enforcement-nginx.

-- MaggieO
Source: StackOverflow