2

The docs say:

When the custom-http-errors option is enabled, the Ingress controller configures NGINX so that it passes several HTTP headers down to its default-backend in case of error: https://kubernetes.github.io/ingress-nginx/user-guide/custom-errors/

I have healthchecks on my services, and want a custom error page to be shown if the healthcheck fails and the service is offline, rather than the default rather terse Nginx one.

I have a default backed configured, and with: custom-http-errors: "503" this works. Without this line, the default Nginx page is shown.

However, if the backend service healthchecks are OK (i.e. "ready"), but the service itself returns a 503 page for any reason, Nginx intercepts this, and also then redirects the client to the default backend, rather than just returning the page to the client like normal.

The docs say:

Setting at least one code also enables proxy_intercept_errors which are required to process error_page.

Which isn't what I want.

So is there any way to have a friendly custom response when the service is broken and the healthchecks checks have failed, without also intercepting legitimate 503 responses from the service?

The same issue applies to 404. I want the ingress to return a friendly 404 page if someone attempts to access a non-existent service, without also intercepting a 404 response from a valid service.

Mark
  • 165
  • 1
  • 5
  • If you are able to express your intention in vanilla nginx config, then you can use [`server-snippet:`](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#server-snippet) to inject that into the controller – mdaniel Jun 12 '20 at 15:42

1 Answers1

3

I've just spent ages trying to work out exactly this problem, and there doesn't seem to be any documented solution out there. So here's what eventually worked for me.

What we really want to do is to not intercept any errors, but instead to change nginx's error page, ideally serving them from our default backend just as we would any intercepted errors.

So you can set up a new location to handle that by adding the following to your ingress controller's ConfigMap:

 server-snippet: |
    location @503 {
      proxy_set_header X-Code 503;
      proxy_set_header X-Format "text/html";
      proxy_pass http://default-backend.ingress-nginx;
    }

(assuming you have your default backend deployed with a service called default-backend in a namespace called ingress-nginx).

Then on the Ingress you want this behaviour you can add an annotation to redirect 503 errors to our new route:

 annotations:
   nginx.ingress.kubernetes.io/configuration-snippet: |
     error_page 503 = @503;

Now the 503 error that would have been served from nginx directly is now served from your default backend, without intercepting any "real" 503s that could be returned from your app's pods when they are eventually up and running.