Custom Errors Backend Configuration for Nginx Ingress Controller

4/29/2020

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.

-- tony tony
devops
dockerfile
kubernetes
nginx-config
nginx-ingress

1 Answer

5/4/2020

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.

-- MaggieO
Source: StackOverflow