I'm trying to deploy a static website to a Kubernetes cluster which is using the official Nginx Ingress controller. The folder structure of the website looks somewhat like this:
/
├── about
│ └── index.html
├── casestudy
│ ├── data-and-analytics
│ │ └── index.html
│ └── workflow-automation
│ └── index.html
├── contact
│ └── index.html
├── css
│ ├── font-awesome.min.css
│ ├── fonts
│ │ ├── slick.eot
│ │ ├── slick.svg
│ │ ├── slick.ttf
│ │ └── slick.woff
│ ├── footer.css
│ ├── layout.css
...
My ingress definition looks like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: website-ingress
annotations:
kubernetes.io/ingress.class: nginx
# nginx.ingress.kubernetes.io/rewrite-target: /$2
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- website.com
secretName: website-tls
rules:
- host: website.com
http:
paths:
- path: /
backend:
serviceName: website-svc
servicePort: 8080
This works fine for the most part, except that if I forget to put a trailing slash at the end of the URL like https://website.com/about
I get routed into an error page. I understand why this is happening - Nginx is looking for a about.html
file and is failing to find one. But I don't know how to fix this.
What I'd ideally like to do is that I want to add a trailing /
to requests which don't have one. But I also want to not do this when the browser is requesting for a css file.
What redirect annotation and rule should I use for this?
Thanks.
Try this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: website-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1/
spec:
rules:
- http:
paths:
- path: /(.*)
backend:
serviceName: website-svc
servicePort: 8080
It works perfectly for me. After running:
curl <ingress ip>/about
You can see in logs the following:
ingress controller
kubectl logs -n ingress-nginx ingress-nginx-controller-6dc856845b-rf2ft
<ip address> - - [29/Dec/2020:18:40:13 +0000] "GET /about HTTP/1.1" 200 7 "-" "curl/7.64.0" 83 0.000 [default-nginx-deployment-80] [] 10.0.1.8:80 7 0.000 200 (...)
nginx pod serving the website
kubectl logs nginx-deployment-6c8c7fdf65-w4h4b
10.0.1.10 - - [29/Dec/2020:18:40:13 +0000] "GET /about/ HTTP/1.1" 200 7 "-" "curl/7.64.0" "<ip address>"
What ultimately worked for this situation is a snippet like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: website-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/rewrite-target: /
# Rewrite all URLs not ending with a segment containing . or ? with a trailing slash
# So basically we are rewriting all folder names with a trailing slash.
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^([^.?]*[^/])$ $1/ redirect;
spec:
tls:
- hosts:
- website.com
secretName: website-tls
rules:
- host: website.com
http:
paths:
- path: /
backend:
serviceName: website-svc
servicePort: 8080
This will let us rewrite all URLs ending with a segment containing no .
(period - thus avoiding filenames) and ?
(question mark - thus avoiding all query strings) with a trailing slash. This works for my case.