
En este artículo quiero hablar sobre dos características de NGINX Ingress relacionadas con la visualización de páginas de error personalizadas, así como las limitaciones que existen en ellas y las formas de evitarlas.
1. Cambiar el backend predeterminado
Por defecto, NGINX Ingress usa el backend predeterminado, que realiza la función correspondiente. Esto significa que cuando consultamos Ingress con un host que no está en los recursos de Ingress, obtenemos una página con un código de respuesta 404:

Sin embargo, cada vez más nuestros clientes vienen con una solicitud en lugar del estándar 404 para mostrar su página con el logotipo de la empresa y otras comodidades. Para hacer esto, NGINX Ingress tiene una
capacidad incorporada para anular el
default-backend-service
. La opción del mismo nombre, como argumento, se
namespace/servicename
registro de formato de
namespace/servicename
. El puerto de servicio debe ser 80.
Para hacer esto, cree su propio pod (implementación) y servicio con su aplicación (
una implementación de ejemplo en YAML desde el repositorio ingress-nginx), que se proporcionará en lugar del backend predeterminado.
Aquí hay una pequeña ilustración:
~$ curl -i -XGET http://sadsdasdas.kube-cloud.my/ HTTP/1.1 404 Not Found Date: Mon, 11 Mar 2019 05:38:15 GMT Content-Type: */* Transfer-Encoding: chunked Connection: keep-alive <span>The page you're looking for could not be found.</span>
Por lo tanto, todos los dominios que no se crean explícitamente a través de YAML con
kind: Ingress
entran en el back-end predeterminado. En la lista anterior,
sadsdasdas
convertido en ese dominio.
2. Procesando errores HTTP en la aplicación usando el backend predeterminado
Otra situación son las solicitudes a una aplicación en la que las situaciones HTTP (404, 500, 502 ...) que no procesan tales situaciones (no se generan páginas hermosas correspondientes) terminan con errores HTTP. También puede ser causado por el deseo de los desarrolladores de dar las mismas páginas de error en muchas aplicaciones.
Para implementar este caso en el lado del servidor, necesitamos:
- Siga las instrucciones anteriores del elemento sobre backend predeterminado;
- Agregue la clave
custom-http-errors
a la configuración ConfigMap nginx-ingress, por ejemplo, con un valor de 404,503
(obviamente, corresponde a los códigos de error cubiertos por la nueva regla).
Se obtiene el resultado esperado: cuando la aplicación cliente se está ejecutando y recibe un error con un código de respuesta de 404 o 503, la solicitud se redirigirá automáticamente al nuevo backend predeterminado ...
Sin embargo, al desarrollar una aplicación para backend predeterminado y errores http personalizados, debe tener en cuenta una característica importante:
!!! Important 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.
El hecho es que al redirigir una solicitud, los encabezados contendrán información útil con el código de respuesta anterior e información adicional (una lista completa de ellos está disponible
aquí ).
Esto significa que usted mismo debe
cuidar el código de respuesta correcto .
Aquí hay un ejemplo de la documentación de cómo funciona esto.
Para diferentes aplicaciones: diferentes backend predeterminados
Para que la solución no sea global para todo el clúster, sino que se aplique solo a aplicaciones específicas, primero debe verificar la versión de Ingress. Si coincide con
0.23 o superior , use las anotaciones nativas de Ingress:
- Podemos redefinir
default-backend
para cada Ingreso por medio de la anotación ; - Podemos anular
custom-http-errors
para cada Ingress usando anotaciones .
Como resultado, el recurso Ingress se verá así:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ .Chart.Name }}-app2 annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/custom-http-errors: "404,502" nginx.ingress.kubernetes.io/default-backend: error-pages spec: tls: - hosts: - app2.example.com secretName: wildcard-tls rules: - host: app2.example.com http: paths: - path: / backend: serviceName: {{ .Chart.Name }}-app2 servicePort: 80
En este caso, los errores 404 y 502 serán redirigidos al servicio de páginas de error con todos los encabezados necesarios.
En
versiones anteriores de Ingress, esto no era posible (el
compromiso fatídico en 0.23 ). Y si tiene 2 aplicaciones completamente diferentes ejecutándose en su clúster y desea especificar diferentes servicios de back-end predeterminados y manejar diferentes códigos de error para cada una de ellas, tendrá que usar soluciones alternativas para esto, de las cuales tenemos dos.
Ingreso <0.23: enfoque uno
Esta opción es más simple. Como una aplicación que da sus páginas, tenemos HTML regular, que no sabe cómo mirar los encabezados y dar los códigos de respuesta correctos. Dicha aplicación se implementa con Ingress con url
/error-pages
, y el HTML se proporcionará en el directorio
ws
.
Ilustración en YAML:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ .Chart.Name }}-app2 annotations: kubernetes.io/ingress.class: "nginx" ingress.kubernetes.io/server-snippet: | proxy_intercept_errors on; error_page 500 501 502 503 504 @error_pages; location @error_pages { rewrite ^ /error-pages/other/index.html break; proxy_pass http://error-pages.prod.svc.cluster.local; } spec: tls: - hosts: - app2.example.com secretName: wildcard-tls rules: - host: app2.example.com http: paths: - path: / backend: serviceName: {{ .Chart.Name }}-app2 servicePort: 80
El servicio para esta implementación debe ser del tipo ClusterIP.
Al mismo tiempo, en la aplicación donde manejaremos el error, en Ingress agregamos fragmentos de servidor o fragmentos de configuración con los siguientes contenidos:
nginx.ingress.kubernetes.io /server-snippet: | proxy_intercept_errors on; error_page 500 501 502 503 504 @error_pages; location @error_pages { rewrite ^ /error-pages/ws/index.html break; proxy_pass http://error-pages.prod.svc.cluster.local; }
Ingreso <0.23: enfoque dos
Una opción para una aplicación que puede manejar encabezados ... De todos modos, esta es una ruta más correcta, tomada de errores http personalizados. Usarlo manualmente (copiar) le permitirá no cambiar la configuración global.
Los pasos son los siguientes. Creamos
la misma implementación con una aplicación que puede escuchar los encabezados necesarios y responder correctamente. Agregue aplicaciones de fragmentos de servidor a Ingress con los siguientes contenidos:
nginx.ingress.kubernetes.io /server-snippet: | proxy_intercept_errors off; error_page 404 = @custom_404; error_page 503 = @custom_503; location @custom_404 { internal; proxy_intercept_errors off; proxy_set_header X-Code 404; proxy_set_header X-Format $http_accept; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Namespace $namespace; proxy_set_header X-Ingress-Name $ingress_name; proxy_set_header X-Service-Name $service_name; proxy_set_header X-Service-Port $service_port; proxy_set_header Host $best_http_host; rewrite ^ /error-pages/ws/index.html break; proxy_pass http://error-pages.prod.svc.cluster.local; } location @custom_503 { internal; proxy_intercept_errors off; proxy_set_header X-Code 503; proxy_set_header X-Format $http_accept; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Namespace $namespace; proxy_set_header X-Ingress-Name $ingress_name; proxy_set_header X-Service-Name $service_name; proxy_set_header X-Service-Port $service_port; proxy_set_header Host $best_http_host; rewrite ^ /error-pages/ws/index.html break; proxy_pass http://error-pages.prod.svc.cluster.local; }
Como puede ver, para cada error que queremos manejar, necesita hacer su ubicación, donde se sustituirán todos los encabezados necesarios, como en las
páginas de error personalizadas "nativas". Por lo tanto, podemos crear diferentes páginas personalizadas con errores incluso para ubicaciones y servidores individuales.
PS
Otros del ciclo de consejos y trucos de K8s:
Lea también en nuestro blog: