Custom Kubernetes Ingress Default Backend and Error Pages

kenmoini profile image Ken Moini ・3 min read

When you're setting up a Kubernetes cluster, one of the choices you need to make is what Ingress to use - or what combination of Ingresses (Ingressi?) to use.

I've used a number of Ingress Controllers in Kubernetes clusters on different clouds, and they all have their place and reason. The classic choice however, is the now native Ingress option provided by the Kubernetes project, the nginx-ingress controller.

Wait, what is an Ingress?

In the terms of a Kubernetes cluster, an Ingress Controller is a cluster resource that will route traffic into the services in the cluster, from external requests. This is how mycutedogs.com gets translated and routed to the side-sites/mycutedogs-com namespace/service in the cluster.

Blank and Bleak

When you deploy the Nginx Ingress Controller, you'll see some very basic error pages such as this:


But instead, what if you could make it look something like this:


How this all works

So when you deploy the Nginx Ingress Controller, it listens on the edge of your Kubernetes cluster for traffic. If it does not have a matching service to route to, it'll throw an error. Those errors are served traditionally from the nginx-ingress-controller container, but you can override where those errors are served from with some modifications to the Deployment and ConfigMap.

In order to set up your own custom error pages you'll need to fork my repo, build your own copy of the container image with your own error HTML files, and do some modifications to the corresponding Deployment Config.

Optional: Modify the error pages

If you'd like to set your own default-backend custom error pages, you'll need to do the following steps - if not and you'd just like to use the more spiffy versions I have available, continue to the Deployment steps

  1. Fork my repo: https://github.com/kenmoini/custom-nginx-ingress-errors
  2. Modify the error pages in the www/ directory as you see fit
  3. Connect to Docker Hub, Quay.io, etc to create your own available image
  4. Modify the k8s-deployment.yaml file in the repo to point to your own image.


These instructions assume that you deployed the Ingress Controller in the default ingress-nginx namespace.

1) Clone down my repo: https://github.com/kenmoini/custom-nginx-ingress-errors

git clone https://github.com/kenmoini/custom-nginx-ingress-errors
cd custom-nginx-ingress-errors

2) Deploy to your Kubernetes cluster - the YAML file already targets the nginx-ingress namespace:

kubectl apply -f k8s-deployment.yaml

3) Modify the ingress-nginx/ingress-nginx-controller Deployment and set the value of the --default-backend-service flag to the namespace/svc-name of the newly created error backend, which should be ingress-nginx/nginx-errors by default.

export KUBE_EDITOR="nano" # optional, switch to the Nano editor
kubectl edit deployment/ingress-nginx-controller -n ingress-nginx

apiVersion: apps/v1
kind: Deployment
      - args:
        - /nginx-ingress-controller
        - --configmap=$(POD_NAMESPACE)/nginx-configuration
        - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
        - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
        - --publish-service=$(POD_NAMESPACE)/ingress-nginx
        - --annotations-prefix=nginx.ingress.kubernetes.io
        - --default-backend-service=$(POD_NAMESPACE)/nginx-errors

4) Edit the ingress-nginx/nginx-configuration ConfigMap and add the key:value pair of "custom-http-errors": "404,500,503":

kubectl edit cm/nginx-configuration -n ingress-nginx

apiVersion: v1
kind: ConfigMap
  custom-http-errors: "404,500,503"

5) Test your new error pages by navigating to the Ingress Load Balancer:

$ kc get services -n ingress-nginx
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
ingress-nginx   LoadBalancer   80:32563/TCP,443:30965/TCP   18d
nginx-errors    ClusterIP   <none>           80/TCP                       117m

$ curl -sS

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Error 404</title>

Bonus: Docker Hub Pre-Push Hook

This repo also has an extra file in hooks/pre-hook which creates another tag with the Git repo commit - it's pretty neat!

Posted on May 25 by:

kenmoini profile

Ken Moini


Automation assassin, container conman, DevSecOps debonair, killer of Kubernetes clusters, often found at parties petting the dog.


markdown guide