I have Nginx Ingress controller deployed in Nginx namespace of my kubernetes cluster. I am building a custom backend image and deploying it in Nginx namespace as nginx default backend. Now it should serve custom http error pages like 404, 500 and 503etc.
I built one and deployed using helm-chart with below default.conf file but it is serving index.html for 404 error and serving just default 503 error(not my custom 503.html page)
server {
listen 8080 default_server;
root /var/www/html;
index index.html;
location / {
}
location /healthz {
access_log off;
return 200 "healthy\n";
}
location /metrics {
stub_status on;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
error_page 500 /500.html;
location = /500.html {
internal;
}
error_page 503 /503.html;
location = /503.html {
internal;
}
}
Dockerfile
FROM nginxinc/nginx-unprivileged
USER root
RUN rm /etc/nginx/conf.d/default.conf && \
ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY content/ /var/www/html/
CMD ["nginx", "-g", "daemon off;"]
Please ask me if you need more info. Your help will be much appreciated, Thanks.
To update the default error page, edit the config map of nginx-ingress-controller. Insert a new key custom-http-errors with the HTTP status code that you want to change its error page, such as:
apiVersion: v1
kind: ConfigMap
data:
custom-http-errors: 404,413,503
enable-vts-status: "false"
metadata:
labels:
app: nginx-ingress
chart: nginx-ingress-1.6.0
component: controller
heritage: Tiller
release: nginx-ingress
name: nginx-ingress-controller
namespace: Nginx
Now, fire the test command again,
curl -i "[http://err-test.192.168.64.5.nip.io/err?code=413](http://err-test.192.168.64.5.nip.io/err?code=413)"
HTTP/1.1 404 Not Found
Server: nginx/1.15.10
Date: Sun, 05 May 2019 11:36:04 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 21
Connection: closedefault backend - 404
This is NOT what you want. The Nginx ingress controller correctly captures the HTTP status code that we want to customize. However, the default Nginx “default-backend” (Image: k8s.gcr.io/defaultbackend:1.4) just simply returns 404 status regardless of the actual status code that the application intends to return. This will cause a problem if the status code is to be used for other purposes.
In the Nginx Ingress Controller documentation you may see:
The custom backend is expected to return the correct HTTP status code instead of
200
. NGINX does not change the response from the custom default backend.
Then in Dockerfile you have to add path to your defined custom backends errors:
ADD custom-error-pages /
CMD ["/custom-error-pages"]
Build the image and push into docker hub. Redeploy the Nginx helm chart in K3s it looks like:
apiVersion: k3s.cattle.io/v1
kind: HelmChart
metadata:
name: nginx-ingress
namespace: Nginx
spec:
chart: stable/nginx-ingress
targetNamespace: kube-system
valuesContent: |-
defaultBackend:
enabled: true
name: default-backend
image:
repository: your-image/custom-error-page
tag: latest
In k8s simply execute:
helm upgrade nginx-ingress stable/nginx-ingress --set defaultBackendService.enabled=true --set defaultBackend.image.repository=your-image/custom-error-page --set defaultBackend.image.tag=latest
Then test again, execute the same curl command:
➜ curl -i "[http://err-test.192.168.64.5.nip.io/err?code=413](http://err-test.192.168.64.5.nip.io/err?code=413)"
HTTP/1.1 413 Request Entity Too Large
Server: nginx/1.15.10
Date: Sun, 05 May 2019 12:09:21 GMT
Content-Type: */*
Transfer-Encoding: chunked
Connection: close4xx html
You will have the custom error page with the correct HTTP status code.
Since you trap 503 status, scale down the replica.
Execute command:
$ kubectl scale deploy err-status-test --replicas=0
If you will access the application again, you will see the custom error page with the status code shown as 503 which is expected.
More information you can find here: custom-backend-errors.